home *** CD-ROM | disk | FTP | other *** search
/ .net (French) 1996 December / .net Magazine (FR) - Issue 02 - Dec 1996.iso / Utilpers / SUPERQUE / DATA.2 / FILTERS / PSINIT / GS_TYPE1.PS < prev    next >
Text File  |  1995-11-15  |  14KB  |  420 lines

  1. %    Copyright (C) 1994, 1995 Aladdin Enterprises.  All rights reserved.
  2. %    Licensed to Zenographics Inc. (Irvine, California) by Artifex Software Inc.
  3. %    under the OEM Agreement of December 21st, 1993.
  4.  
  5. % Type 1 font support code.
  6.  
  7. % The standard representation for PostScript compatible fonts is described
  8. % in the book "Adobe Type 1 Font Format", published by Adobe Systems Inc.
  9.  
  10. % Define an augmented version of .buildfont1 that inserts UnderlinePosition
  11. % and UnderlineThickness entries in FontInfo if they aren't there already.
  12. % (This works around the incorrect assumption, made by many word processors,
  13. % that these entries are present in the built-in fonts.)
  14. /.buildfont1
  15.  { dup /FontInfo known not
  16.     { .growfontdict dup /FontInfo 2 dict put }
  17.    if
  18.    dup dup /FontInfo get dup dup
  19.    /UnderlinePosition known exch /UnderlineThickness known and
  20.     { pop pop        % entries already present
  21.     }
  22.     { dup length 2 add dict copy
  23.       dup /UnderlinePosition known not
  24.        { dup /UnderlinePosition 3 index /FontBBox get
  25.          1 get 2 div put        % 1/2 the font descent
  26.        }
  27.       if
  28.       dup /UnderlineThickness known not
  29.        { dup /UnderlineThickness 3 index /FontBBox get
  30.          dup 3 get exch 1 get sub 20 div put    % 1/20 the font height
  31.        }
  32.       if
  33.       1 index /FontInfo get wcheck not { readonly } if
  34.       /FontInfo exch put
  35.     }
  36.    ifelse //.buildfont1
  37.  } bind def
  38.  
  39. % If DISKFONTS is true, we load individual CharStrings as they are needed.
  40. % (This is intended primarily for machines with very small memories.)
  41. % Initially, the character definition is the file position of the definition;
  42. % this gets replaced with the actual CharString.
  43. % Note that if we are loading characters lazily, CharStrings is writable.
  44.  
  45. % _Cstring must be long enough to hold the longest CharString for
  46. % a character defined using seac.  This is lenIV + 4 * 5 (for the operands
  47. % of sbw, assuming div is not used) + 2 (for sbw) + 3 * 5 (for the operands
  48. % of seac other than the character codes) + 2 * 2 (for the character codes)
  49. % + 2 (for seac), i.e., lenIV + 43.
  50.  
  51. /_Cstring 60 string def
  52.  
  53. % When we initially load the font, we call
  54. %    <index|charname> <length> <readproc> cskip_C
  55. % to skip over each character definition and return the file position instead.
  56. % This substitutes for the procedure
  57. %    <index|charname> <length> string currentfile exch read[hex]string pop
  58. %      [encrypt]
  59. % What we actually store is fileposition * 1000 + length,
  60. %   negated if the string is stored in binary form.
  61.  
  62. % Older fonts use skip_C rather than cskip_C.
  63. % skip_C takes /readstring or /readhexstring as its third argument,
  64. % instead of the entire reading procedure.
  65. /skipproc_C {string currentfile exch readstring pop} cvlit def
  66. /skip_C
  67.  { //skipproc_C dup 3 4 -1 roll put cvx readonly cskip_C
  68.  } bind def
  69. /cskip_C
  70.  { exch dup 1000 ge 3 index type /nametype ne or
  71.     { % This is a Subrs string, or the string is so long we can't represent
  72.       % its length.  Load it now.
  73.       exch exec
  74.     }
  75.     { % Record the position and length, and skip the string.
  76.       dup currentfile fileposition 1000 mul add
  77.       2 index 3 get /readstring cvx eq { neg } if
  78.       3 1 roll
  79.       dup _Cstring length idiv
  80.        { currentfile _Cstring 3 index 3 get exec pop pop
  81.        } repeat
  82.       _Cstring length mod _Cstring exch 0 exch getinterval
  83.       currentfile exch 3 -1 roll 3 get exec pop pop
  84.     }
  85.    ifelse
  86.  } bind def
  87.  
  88. % Type1BuildGlyph calls load_C to actually load the character definition.
  89.  
  90. /load_C        % <charname> <fileposandlength> load_C -
  91.  { dup abs 1000 idiv FontFile exch setfileposition
  92.    CharStrings 3 1 roll
  93.    dup 0 lt
  94.     { neg 1000 mod string FontFile exch readstring }
  95.     { 1000 mod string FontFile exch readhexstring }
  96.    ifelse pop
  97. % If the CharStrings aren't encrypted on the file, encrypt now.
  98.    Private /-| get 0 get
  99.    dup type /nametype ne { dup length 5 sub 5 exch getinterval exec } { pop } ifelse
  100.    dup 4 1 roll put
  101. % If the character is defined with seac, load its components now.
  102.    mark exch seac_C
  103.    counttomark
  104.     { StandardEncoding exch get dup CharStrings exch get
  105.       dup type /integertype eq { load_C } { pop pop } ifelse
  106.     } repeat
  107.    pop        % the mark
  108.  } bind def
  109.  
  110. /seac_C        % <charstring> seac_C <achar> <bchar> ..or nothing..
  111.  { dup length _Cstring length le
  112.     { 4330 exch _Cstring .type1decrypt exch pop
  113.       dup dup length 2 sub 2 getinterval <0c06> eq    % seac
  114.        { dup length
  115.          Private /lenIV known { Private /lenIV get } { 4 } ifelse
  116.      exch 1 index sub getinterval
  117. % Parse the string just enough to extract the seac information.
  118. % We assume that the only possible operators are hsbw, sbw, and seac,
  119. % and that there are no 5-byte numbers.
  120.      mark 0 3 -1 roll
  121.       { exch
  122.          { { dup 32 lt
  123.               { pop 0 }
  124.           { dup 247 lt
  125.              { 139 sub 0 }
  126.              { dup 251 lt
  127.             { 247 sub 256 mul 108 add 1 1 }
  128.             { 251 sub -256 mul -108 add -1 1 }
  129.                ifelse
  130.              }
  131.             ifelse
  132.           }
  133.          ifelse
  134.            }            % 0
  135.            { mul add 0 }        % 1
  136.          }
  137.         exch get exec
  138.       }
  139.      forall pop
  140.      counttomark 1 add 2 roll cleartomark    % pop all but achar bchar
  141.        }
  142.        { pop    % not seac
  143.        }
  144.       ifelse
  145.     }
  146.     { pop    % punt
  147.     }
  148.    ifelse
  149.  } bind def
  150.  
  151. % Define an auxiliary procedure for loading a font.
  152. % If DISKFONTS is true and the body of the font is not encrypted with eexec:
  153. %    - Prevent the CharStrings from being made read-only.
  154. %    - Substitute a different CharString-reading procedure.
  155. % (eexec disables this because the implicit 'systemdict begin' hides
  156. % the redefinitions that make the scheme work.)
  157. % We assume that:
  158. %    - The magic procedures (-|, -!, |-, and |) are defined with
  159. %    executeonly or readonly;
  160. %    - The contents of the reading procedures are as defined in bdftops.ps;
  161. %    - The font includes the code
  162. %    <font> /CharStrings <CharStrings> readonly put
  163. /.loadfontdict 6 dict def mark
  164.  /begin            % push this dict after systemdict
  165.   { dup begin
  166.     //systemdict eq { //.loadfontdict begin } if
  167.   } bind
  168.  /end            % match begin
  169.   { currentdict end
  170.     //.loadfontdict eq currentdict //systemdict eq and { end } if
  171.   } bind
  172.  /dict            % leave room for FontFile
  173.   { 1 add dict
  174.   } bind
  175.  /executeonly        % for reading procedures
  176.   { readonly
  177.   }
  178.  /noaccess        % for Subrs strings and Private dictionary
  179.   { readonly
  180.   }
  181.  /readonly        % for procedures and CharStrings dictionary
  182.   {    % We want to take the following non-standard actions here:
  183.       %   - If the operand is the CharStrings dictionary, do nothing;
  184.     %   - If the operand is a number (a file position replacing the
  185.     %    actual CharString), do nothing;
  186.     %   - If the operand is either of the reading procedures (-| or -!),
  187.     %    substitute a different one.
  188.     dup type /dicttype eq        % CharStrings or Private
  189.     count 2 gt and
  190.      { 1 index /CharStrings ne { readonly } if }
  191.      { dup type /arraytype eq        % procedure or data array
  192.     { dup length 5 ge 1 index xcheck and
  193.        { dup 0 get /string eq
  194.          1 index 1 get /currentfile eq and
  195.          1 index 2 get /exch eq and
  196.          1 index 3 get dup /readstring eq exch /readhexstring eq or and
  197.          1 index 4 get /pop eq and
  198.           { /cskip_C cvx 2 packedarray cvx
  199.           }
  200.           { readonly
  201.           }
  202.          ifelse
  203.        }
  204.        { readonly
  205.        }
  206.       ifelse
  207.     }
  208.     { dup type /stringtype eq    % must be a Subr string
  209.        { readonly }
  210.       if
  211.     }
  212.        ifelse
  213.      }
  214.     ifelse
  215.   } bind
  216. counttomark 2 idiv { .loadfontdict 3 1 roll put } repeat pop
  217. .loadfontdict readonly pop
  218. /.loadfont        % <file> .loadfont -
  219.  { mark exch systemdict begin
  220.    DISKFONTS { .loadfontdict begin } if
  221.    % We really would just like systemdict on the stack,
  222.    % but fonts produced by Fontographer require a writable dictionary....
  223.    userdict begin
  224.     % We can't just use `run', because we want to check for .PFB files.
  225.    currentpacking
  226.     { false setpacking .loadfont1 true setpacking }
  227.     { .loadfont1 }
  228.    ifelse
  229.     { stop } if
  230.    end
  231.    DISKFONTS { end } if
  232.    end cleartomark
  233.  } bind def
  234. /.loadfont1        % <file> .loadfont1 <errorflag>
  235.  {    % We would like to use `false /PFBDecode filter',
  236.     % but this occasionally produces a whitespace character as
  237.     % the first of an eexec section, so we can't do it.
  238.     % Also, since the real input file never reaches EOF if we are using
  239.     % a PFBDecode filter (the filter stops just after reading the last
  240.     % character), we must explicitly close the real file in this case.
  241.     % Since the file might leave garbage on the operand stack,
  242.     % we have to create a procedure to close the file reliably.
  243.     { dup read not { -1 } if
  244.       2 copy unread 16#80 eq
  245.        { [ exch dup true /PFBDecode filter cvx exch cvlit
  246.          systemdict /closefile get ]
  247.        }
  248.       if cvx exec
  249.     } stopped
  250.    $error /newerror get and
  251.  } bind def
  252.  
  253.  
  254. % The CharStrings are a dictionary in which the key is the character name,
  255. % and the value is a compressed and encrypted representation of a path.
  256. % For detailed information, see the book "Adobe Type 1 Font Format",
  257. % published by Adobe Systems Inc.
  258.  
  259. % Here are the BuildChar and BuildGlyph implementation for Type 1 fonts.
  260. % The names Type1BuildChar and Type1BuildGlyph are known to the interpreter.
  261.  
  262. /Type1BuildChar        % <font> <code> Type1BuildChar -
  263.  { 1 index /Encoding get 1 index get .type1build
  264.  } bind def
  265. /Type1BuildGlyph    % <font> <name> Type1BuildGlyph -
  266.  { dup .type1build
  267.  } bind def
  268. /.type1build        % <font> <code|name> <name> .type1build -
  269.  { 3 -1 roll begin
  270.     dup CharStrings exch .knownget not
  271.      { 2 copy eq { exch pop /.notdef exch } if
  272.        QUIET not
  273.     { (Substituting .notdef for ) print = flush }
  274.     { pop }
  275.        ifelse
  276.        /.notdef CharStrings /.notdef get
  277.      } if
  278.     % stack: codename charname charstring
  279.     PaintType 0 ne
  280.      {    % Any reasonable implementation would execute something like
  281.     %    1 setmiterlimit 0 setlinejoin 0 setlinecap
  282.     % here, but apparently the Adobe implementations aren't reasonable.
  283.        currentdict /StrokeWidth .knownget not { 0 } if
  284.        setlinewidth
  285.      } if
  286.     dup type /stringtype eq        % encoded outline
  287.      { 3 -1 roll pop 0 0 moveto outline_C
  288.      }
  289.      { dup type /integertype eq        % file position for lazy loading
  290.     { 3 -1 roll pop
  291.       1 index exch load_C dup CharStrings exch get
  292.       0 0 moveto outline_C
  293.     }
  294.     {                % PostScript procedure
  295.       exch pop
  296.       currentdict end systemdict begin begin   exec   end
  297.     }
  298.        ifelse
  299.      }
  300.     ifelse
  301.    end
  302.  } bind def
  303.  
  304. % Expand the bounding box before calling setcachedevice.
  305. % Because of square caps and miter joins, the maximum expansion on each side
  306. % is max(sqrt(2), miter_limit) * line_width/2.
  307. % (setcachedevice adds the necessary 1- or 2-pixel fuzz.)
  308. /expandbox_C        % <llx> <lly> <urx> <ury> expandbox_C <...ditto...>
  309.  { PaintType 0 ne
  310.     { 1.415 currentmiterlimit max currentlinewidth mul 2 div
  311.             % llx lly urx ury exp
  312.       5 1 roll 4 index add
  313.             % exp llx lly urx ury+
  314.       5 1 roll 3 index add
  315.             % ury+ exp llx lly urx+
  316.       5 1 roll 2 index sub
  317.             % urx+ ury+ exp llx lly-
  318.       5 1 roll exch sub
  319.             % lly- urx+ ury+ llx-
  320.       4 1 roll
  321.     }
  322.    if
  323.  } bind def
  324.  
  325. % Make the call on setcachedevice a separate procedure, so we can redefine it
  326. % if the composite font extensions are present.
  327. /setcache_C where        % gs_type0.ps might be loaded first!
  328.  { pop }
  329.  { /setcache_C { setcachedevice pop } bind def }
  330. ifelse
  331.  
  332. /outline_C        % <charname> <charstring> outline_C -
  333.  {    % In order to make character oversampling work, we must
  334.     % set up the cache before calling .type1addpath.
  335.     % To do this, we must get the bounding box from the FontBBox,
  336.     % and the width and left side bearing from the CharString.
  337.     % (If the FontBBox isn't valid, we punt.)
  338.    currentdict /FontBBox .knownget
  339.     { dup length 4 eq
  340.        { aload pop
  341.      dup 3 index gt 2 index 5 index gt and
  342.       { bbox_C }
  343.       { pop pop pop pop nobbox_C }
  344.      ifelse
  345.        }
  346.        { pop nobbox_C
  347.        }
  348.       ifelse
  349.     }
  350.     { nobbox_C
  351.     }
  352.    ifelse
  353.    PaintType 0 eq { fill } { stroke } ifelse
  354.  } bind def
  355.  
  356. % Handle the case where FontBBox is not valid.
  357. % In this case, we do the .type1addpath first, then the setcachedevice.
  358. % Oversampling is not possible.
  359. /nobbox_C        % <charname> <charstring> nobbox_C -
  360.  { currentdict /Metrics .knownget
  361.     { 2 index .knownget
  362.        { dup type dup /integertype eq exch /realtype eq or
  363.           {    % <wx>
  364.         exch .type1addpath 0
  365.       }
  366.       { dup length 2 eq
  367.          {    % [<sbx> <wx>]
  368.            exch 1 index 0 get 0 .type1addpath
  369.            1 get 0
  370.          }
  371.          {    % [<sbx> <sby> <wx> <wy>]
  372.            aload pop 5 2 roll .type1addpath
  373.          }
  374.         ifelse
  375.       }
  376.      ifelse
  377.        }
  378.        { .type1addpath currentpoint
  379.        }
  380.       ifelse
  381.     }
  382.     { .type1addpath currentpoint
  383.     }
  384.    ifelse        % stack: wx wy
  385.    pathbbox expandbox_C setcache_C
  386.  } bind def
  387.  
  388. % Handle the case where FontBBox is valid.
  389. /bbox_C            % <charname> <charstring> <llx> ... <ury> bbox_C -
  390.  {    % Get the width and l.s.b. by parsing the CharString.
  391.     % This isn't needed if we have a 4-element Metrics array,
  392.     % but those are rare.
  393.    4 index .type1getsbw
  394.             % stack: cname cstring llx lly urx ury sbx sby wx wy
  395.    currentdict /Metrics .knownget
  396.     { 10 index .knownget
  397.        { dup type dup /integertype eq exch /realtype eq or
  398.           {    % <wx>
  399.         exch pop exch pop 0
  400.       }
  401.       { 5 1 roll pop pop pop pop
  402.         dup length 2 eq
  403.          {    % [<sbx> <wx>]
  404.            aload pop 0 exch 0
  405.          }
  406.          {    % [<sbx> <sby> <wx> <wy>]
  407.            aload pop
  408.          }
  409.         ifelse
  410.       }
  411.      ifelse
  412.        }
  413.       if
  414.     }
  415.    if
  416.    8 4 roll expandbox_C
  417.    9 index 7 1 roll setcache_C
  418.    .type1addpath pop
  419.  } bind def
  420.